import { getStorage, removeStorage, setStorage } from '@/utils/storage.js'
import axios from 'axios'
import 'element-plus/theme-chalk/index.css'
import { refreshToken } from '@/api/User.js'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
import CryptoJS from 'crypto-js'

// 是否开启参数加密
const VITE_ENCRYPTION_ENABLED = import.meta.env.VITE_ENCRYPTION_ENABLED === 'true';

// 加密密钥和IV
const key = CryptoJS.enc.Utf8.parse('1234567891234567')
const iv = CryptoJS.enc.Utf8.parse('1234567891234567')

// 加密
function encrypt(text) {
  const cipher = CryptoJS.AES.encrypt(text, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })
  return cipher.toString()
}

// 解密
function decrypt(ciphertext) {
  const bytes = CryptoJS.AES.decrypt(ciphertext, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })
  return bytes.toString(CryptoJS.enc.Utf8)
}

// 为requestId生成UUID
function getUuid() {
  const hexDigits = '0123456789abcdef'
  let s = Array.from({ length: 32 }, () => hexDigits[Math.floor(Math.random() * 0x10)])
  s[14] = '4'
  s[19] = hexDigits[(s[19] & 0x3) | 0x8]
  s[8] = s[13] = s[18] = s[23] = '-'
  return s.join('')
}

// 按ASCII顺序对对象键进行排序并删除空值
function sortASCII(obj) {
  const cleanedObj = removeEmptyValues(obj)
  const sortedObj = {}
  Object.keys(cleanedObj).sort().forEach(key => {
    sortedObj[key] = cleanedObj[key]
  })
  return sortedObj
}

// 删除对象中的空值
function removeEmptyValues(obj) {
  const result = {}
  for (const key in obj) {
    if (obj[key] !== null && obj[key] !== undefined && obj[key] !== '') {
      result[key] = obj[key]
    }
  }
  return result
}

const router = useRouter()

const TIME_OUT = 9999999999
const BASE_URL = import.meta.env.VITE_BASE_API

// 1. 创建新的axios实例，
const service = axios.create({
  // 超时时间 单位是ms，这里设置了3s的超时时间
  timeout: TIME_OUT,
  baseURL: BASE_URL,
  // 500错误
  validateStatus: function(status) {
    return status <= 999
  }
})

const serviceshed = []
// 2.请求拦截器
service.interceptors.request.use(
  (config) => {
    if (isExist(config.url)) {
      return Promise.reject('重复请求!')
    }
    serviceshed.push(config.url)
    config.headers = {
      'Content-Type': 'application/json;charset=UTF-8' // 配置请求头
    }
    const isToken = config.setting?.isToken
    if (isToken) {
      config.headers['Authorization'] = getStorage('TOKEN') // 让每个请求携带自定义token 请根据实际情况自行修改
    }
    const isRefresh = config.setting?.isRefresh
    if (isRefresh) {
      config.headers['refreshToken'] = getStorage('REFRESH_TOKEN')
    }
    const params = config.params || {}
    if (config.method?.toUpperCase() === 'GET' && params) {
      let url = config.url + '?'
      for (const propName of Object.keys(params)) {
        const value = params[propName]
        if (value !== 0 && value !== null && typeof value !== 'undefined') {
          if (typeof value === 'object') {
            for (const val of Object.keys(value)) {
              const params = propName + '[' + val + ']'
              const subPart = encodeURIComponent(params) + '='
              url += subPart + encodeURIComponent(value[val]) + '&'
            }
          } else {
            url += `${propName}=${encodeURIComponent(value)}&`
          }
        }
      }
      // 给 get 请求加上时间戳参数，避免从缓存中拿数据
      // const now = new Date().getTime()
      // params = params.substring(0, url.length - 1) + `?_t=${now}`
      url = url.slice(0, -1)
      config.params = {}
      config.url = url
    }

    if (VITE_ENCRYPTION_ENABLED === true) {
      // 加密和签名
      const timestamp = Date.now()
      const requestId = getUuid()
      const data = JSON.stringify(sortASCII(config.data))
      const sign = CryptoJS.MD5(data + requestId + timestamp)
      config.headers['timestamp'] = timestamp
      config.headers['requestId'] = requestId
      config.headers['sign'] = sign
      config.data = encrypt(data)
    }

    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  (config) => {
    removeShed(config.url)

    if (VITE_ENCRYPTION_ENABLED === true) {
      // 解密
      // 去除空格
      config.data = config.data.replace(' ', '')
      // 如果是返回的文件
      if (config.config.responseType === 'blob') {
        config.data = decrypt(config.data)
        return config.data
      }
      // 兼容服务端返回的字符串数据
      if (typeof config.data === 'string') {
        config.data = decrypt(config.data)
        config.data = config.data ? JSON.parse(config.data) : config.data
      }
    }

    if (config?.config?.setting?.responseType) {
      return config
    }
    if (config.status === 500) {
      ElMessage.error(config.data.msg)
      return config.data || {}
    }
    if (config.status === 401) {
      //获取refresh_token
      let refresh_token = getStorage('REFRESH_TOKEN')
      if (refresh_token) {
        //刷新token
        refreshToken(refresh_token).then(res => {
          if (res.code === 1) {
            //先删除
            removeStorage('TOKEN')
            removeStorage('REFRESH_TOKEN')
            //再添加
            setStorage('TOKEN', res.data.accessToken)
            setStorage('REFRESH_TOKEN', res.data.refreshToken)
            window.location.reload()
          } else {
            console.log('刷新token失败')
            removeStorage('TOKEN')
            removeStorage('REFRESH_TOKEN')
            router.push({ path: '/login' })
          }
        })
      } else {
        removeStorage('TOKEN')
        removeStorage('REFRESH_TOKEN')
        router.push({ path: '/login' })
      }
    }
    return config.data || {}
  },
  (error) => {
    return Promise.reject(error)
  }
)

const isExist = (url) => {
  return serviceshed.find((ele) => ele == url)
}

const removeShed = (url) => {
  const index = serviceshed.findIndex((ele) => ele == url)
  serviceshed.splice(index, 1)
}

// 4.导入文件
export default service
